package com.econ.powercloud.ems.config;

import com.econ.powercloud.ems.common.enums.AlarmOrFaultState;
import com.econ.powercloud.ems.common.enums.StatusTypeCode;
import com.econ.powercloud.ems.constant.SysConstant;
import com.econ.powercloud.ems.dal.entity.*;
import com.econ.powercloud.ems.service.dao.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

@Component
public class InitParameter {
    @Autowired
    private EmsDeviceDAO emsDeviceDAO;
    @Autowired
    private EmsDeviceCalConfigDAO emsDeviceCalConfigDAO;
    @Autowired
    private IotProductYxDAO iotProductYxDAO;
    @Autowired
    private EmsProtectSoePidConfigDAO emsProtectSoePidConfigDAO;
    @Autowired
    private EmsProtectSectionConfigDAO emsProtectSectionConfigDAO;
    @Autowired
    private EmsProtectSoeConfigDAO emsProtectSoeConfigDAO;
    @Autowired
    private EmsWarnConfigDAO emsWarnConfigDAO;
    @Autowired
    private EmsYcYxStrategyConfigDAO emsYcYxStrategyConfigDAO;

    @Scheduled(cron = "0 */10 * * * ?")
    public void refreshCacheTiming(){
        refreshCache();
    }

    @PostConstruct
    public void init(){
        //这些数据只需要重启时加载一次即可
        initIncomeDayReportHead();
        initFeeConfirmReportHead();
        //这些数据需要在一定时间内刷新
        refreshCache();
    }

    /**
     * 刷新缓存操作
     */
    public void refreshCache(){
        initNeedDealComputeCode();
        initFaultDit();
        initModuleCodeToDevice();
        initProtectSoePidConfigMap();
        initProtectSectionConfigMap();
        initProtectSoeConfigMap();
        initWarnConfigList();
        initStrategyConfigMap();
    }

    /**
     * 初始化受益报表 储能装置 日报表表头
     */
    public void initIncomeDayReportHead(){
        List<String> list = Lists.newArrayList("category","project","currentRead","beforeRead","electricity",
                "price","amount");
        EMSStaticMap.incomeDayReportHead = list;
    }

    /**
     * 初始化电费结算确认表 报表表头
     */
    public void initFeeConfirmReportHead(){
        List<String> list = Lists.newArrayList("category","project","currentRead","beforeRead","electricity","amount");
        EMSStaticMap.feeConfirmReportHead = list;
    }

    /**
     * 对于计算点号的一些数据做特殊化处理
     */
    public void initNeedDealComputeCode(){
        List<EmsDeviceCalConfig> calConfigList = emsDeviceCalConfigDAO.list();
        Map<String,Integer> calComputeToComplexType = Maps.newConcurrentMap();
        calConfigList.stream().forEach(d->{
            calComputeToComplexType.put(d.getComputeCode(),d.getComplex());
        });
        EMSStaticMap.calComputeToComplexType = calComputeToComplexType;
    }

    /**
     * 初始化故障告警点号
     */
    public void initFaultDit(){
        //只筛选故障告警点号
        List<IotProductYx> yxSyncList = iotProductYxDAO.list().stream().filter(d-> StatusTypeCode.judgeAlarmFaultFromCode(d.getStatusTypeCode())).collect(Collectors.toList());
        if(CollectionUtils.isEmpty(yxSyncList)){
            EMSStaticMap.faultDitMap.clear();
            return;
        }
        Map<String,Map<String,Integer>> faultDitMap = Maps.newConcurrentMap();
        Map<String,List<IotProductYx>> productYxMap = yxSyncList.stream().collect(Collectors.groupingBy(d->d.getProductKey()));
        productYxMap.forEach((k,v)->{
            Map<String,Integer> map = Maps.newHashMap();
            v.stream().forEach(d->{
                map.put(d.getDit(),StatusTypeCode.ALERT.getCode().equals(d.getStatusTypeCode())? AlarmOrFaultState.ALARM.getCode():
                        AlarmOrFaultState.FAULT.getCode());
            });
            faultDitMap.put(k,map);
        });
        EMSStaticMap.faultDitMap = faultDitMap;
    }

    /**
     * 初始化EMSDevice中的根设备
     */
    public void initModuleCodeToDevice(){
        List<EmsDevice> emsDeviceList = emsDeviceDAO.list().stream().collect(Collectors.toList());
        if(CollectionUtils.isEmpty(emsDeviceList)){
            EMSStaticMap.moduleCodeToDeviceMap.clear();
            return;
        }
        Map<String, EmsDevice> moduleCodeToDeviceMap = Maps.newConcurrentMap();
        emsDeviceList.stream().forEach(d->{
            moduleCodeToDeviceMap.put(d.getInitDeviceCode() + SysConstant.SPOT + (d.getModuleCode()==null?"def":d.getModuleCode()),d);
        });
        EMSStaticMap.moduleCodeToDeviceMap = moduleCodeToDeviceMap;
    }

    /**
     * 初始化initProtectSoePidConfigMap
     */
    public void initProtectSoePidConfigMap(){
        List<EmsProtectSoePidConfig> emsProtectSoePidConfigs = emsProtectSoePidConfigDAO.list();
        if(CollectionUtils.isEmpty(emsProtectSoePidConfigs)){
            EMSStaticMap.protectSoePidConfigMap.clear();
            return;
        }
        Map<String,EmsProtectSoePidConfig> protectSoePidConfigMap = Maps.newConcurrentMap();
        emsProtectSoePidConfigs.stream().forEach(d->{
            protectSoePidConfigMap.put(d.getEventPid(),d);
        });
        EMSStaticMap.protectSoePidConfigMap = protectSoePidConfigMap;
    }

    /**
     * 初始化initProtectSectionConfigMap
     */
    public void initProtectSectionConfigMap(){
        List<EmsProtectSectionConfig> emsProtectSectionConfigs = emsProtectSectionConfigDAO.list();
        if(CollectionUtils.isEmpty(emsProtectSectionConfigs)){
            EMSStaticMap.protectSectionConfigMap.clear();
            return;
        }
        EMSStaticMap.protectSectionConfigMap = emsProtectSectionConfigs.stream().collect(Collectors.groupingBy(d->d.getInitDeviceCode()));
    }

    /**
     * 初始化initProtectSoeConfigMap
     */
    public void initProtectSoeConfigMap(){
        List<EmsProtectSoeConfig> emsProtectSoeConfigs = emsProtectSoeConfigDAO.list();
        if(CollectionUtils.isEmpty(emsProtectSoeConfigs)){
            EMSStaticMap.protectSoeConfigMap.clear();
            return;
        }
        Map<String,Map<String, EmsProtectSoeConfig>> protectSoeConfigMap = Maps.newConcurrentMap();
        Map<String,List<EmsProtectSoeConfig>> initDeviceCodeMap = emsProtectSoeConfigs.stream().collect(Collectors.groupingBy(d->d.getInitDeviceCode()));
        initDeviceCodeMap.forEach((k,v) -> {
            protectSoeConfigMap.put(k,v.stream().collect(Collectors.toMap(d->d.getType() + SysConstant.CABLE + d.getVal(),d->d,(p1,p2)->p1)));
        });
        EMSStaticMap.protectSoeConfigMap = protectSoeConfigMap;
    }

    public void initWarnConfigList(){
        EMSStaticMap.emsWarnConfigPid.clear();
        List<EmsWarnConfig> emsWarnConfigList = emsWarnConfigDAO.list();
        if(CollectionUtils.isEmpty(emsWarnConfigList)){
            return;
        }
        EMSStaticMap.emsWarnConfigPid = emsWarnConfigList.stream().map(d->d.getPid()).collect(Collectors.toList());
    }

    public void initStrategyConfigMap(){
        EMSStaticMap.emsYcYxStrategyConfigMap.clear();
        List<EmsAdditionalOperationConfig> emsAdditionalOperationConfigList = emsYcYxStrategyConfigDAO.list();
        if(CollectionUtils.isEmpty(emsAdditionalOperationConfigList)){
            return;
        }
        EMSStaticMap.emsYcYxStrategyConfigMap = emsAdditionalOperationConfigList.stream().collect(Collectors.groupingBy(EmsAdditionalOperationConfig::getPid));
    }
}
